Balancing equations

Author
Affiliation

Minjae Park

Auburn University
MATH 2660 - Spring 2026

Published

April 15, 2026

Overview

Main idea

  • Today we explore one theme: local balance creates linear equations.
  • First example: voltages on a resistor network.
  • Second example: traffic flowing through a road network.
  • In both cases, we write equations from conservation.
  • Then MATLAB helps us solve and visualize the answer.

Plan

  1. Build a voltage model on an irregular network
  2. Solve and visualize the node voltages
  3. Build a traffic model from flow balance
  4. Solve and visualize the road flows
  5. Briefly compare solver choices

Balancing models

Setting Unknowns live on Balance law
Voltage network nodes current in = current out
Traffic network edges flow in = flow out
Ecology populations or masses in compartments inflow = outflow at equilibrium
Finance asset positions portfolio cash flows = target obligations
Markov chain probabilities on states probability in = probability out at steady state
Tutte embedding node coordinates each interior point = average of its neighbors

Companion file

  • The MATLAB script for today is scripts/balancing_equations_demo.m
  • It contains:
    • an irregular resistor-network example
    • a small traffic-flow example
    • a short LU / Cholesky / QR comparison

Voltage

Voltage balance at an interior node

  • Put a voltage \(u_i\) at each node.
  • If edge \(i \sim j\) has resistance \(R_{ij}\), then the current from \(i\) to \(j\) is \[ \frac{u_i-u_j}{R_{ij}}. \]
  • It is often cleaner to use the conductance \[ c_{ij} = \frac{1}{R_{ij}}. \]
  • Fix the boundary voltages.
  • At each interior node, Kirchhoff’s current law says \[ \sum_{j \sim i} c_{ij}(u_i - u_j) = 0. \]
  • The unit-resistor case is just the special case \(c_{ij}=1\) for every edge.

Laplacian form

  • Let \(W\) be the weighted adjacency matrix, where \[ W_{ij} = c_{ij}. \]
  • Let \(D\) be the diagonal matrix of weighted degrees \[ d_i = \sum_j W_{ij}. \]
  • Then the weighted Laplacian is \[ L = D - W. \]
  • The balance equations are still \[ (Lu)_i = 0 \qquad \text{for interior nodes.} \]
  • After splitting into boundary and interior vertices, \[ L_{II} u_I = -L_{IB} u_B. \]
  • This is a linear system for the unknown interior voltages.

What do the subscripts mean?

  • I means interior nodes.
  • B means boundary nodes.
  • We split the voltage vector into two pieces: \[ u = \begin{bmatrix} u_I \\ u_B \end{bmatrix} \]
  • Here:
    • u_I = unknown interior voltages
    • u_B = fixed boundary voltages
  • So the subscripts are just telling us which part of the network we are looking at.

Block matrix picture

\[ L = \begin{bmatrix} L_{II} & L_{IB} \\ L_{BI} & L_{BB} \end{bmatrix}, \qquad u = \begin{bmatrix} u_I \\ u_B \end{bmatrix} \]

  • L_{II} means:
    • rows from interior equations
    • columns from interior unknowns
  • L_{IB} means:
    • rows from interior equations
    • columns from boundary values
  • So the interior rows of Lu = 0 become \[ L_{II}u_I + L_{IB}u_B = 0. \]
  • Since u_B is already known, we move that term to the right side.

Tiny index example

  • Suppose the boundary nodes are [1 2 5].

  • Suppose the interior nodes are [3 4].

  • Then MATLAB literally forms

    LII = L([3 4], [3 4]);
    LIB = L([3 4], [1 2 5]);
  • So LII is the part of L that connects interior equations to interior unknowns.

  • And LIB is the part that tells us how the boundary values influence those same interior equations.

Build an irregular network

mask = logical([
    1 1 1 1 0 0 0 0;
    1 1 1 1 1 1 0 0;
    1 1 1 1 1 1 1 0;
    1 1 1 1 1 1 1 1;
    0 1 1 1 1 1 1 1;
    0 0 1 1 1 1 1 1
]);

[m,n] = size(mask);
node_id = zeros(m,n);
coords = [];
N = 0;

for r = 1:m
    for c = 1:n
        if mask(r,c)
            N = N + 1;
            node_id(r,c) = N;
            coords(N,:) = [c, m-r+1];
        end
    end
end
  • We start from a grid, then remove some nodes.
  • The irregular shape makes the voltage pattern more interesting.

Assign edge resistances

s = edges(:,1);
t = edges(:,2);
x0 = coords(:,1);
y0 = coords(:,2);

resistance = zeros(length(s), 1);

for k = 1:length(s)
    if y0(s(k)) == y0(t(k))
        resistance(k) = 1;
    else
        resistance(k) = 2;
    end
end

conductance = 1 ./ resistance;
  • Here we make a simple nonuniform example:
    • horizontal edges have resistance 1
    • vertical edges have resistance 2
  • Lower resistance means larger conductance.
  • If every resistance were 1, we would get the old unit-resistor model.

Build the weighted Laplacian

C = full(sparse(s, t, conductance, N, N));
C = C + C.';
deg = sum(C, 2);
L = diag(deg) - C;
  • C(i,j) stores the conductance between nodes i and j.
  • The diagonal entry deg(i) is the total conductance connected to node i.
  • The formula L = D - C looks the same as before, but now the entries carry resistance information.

Solve the voltage system

G = graph(s, t);

% rows = interior equations, columns = interior unknowns
LII = L(interior, interior);

% rows = interior equations, columns = boundary values
LIB = L(interior, boundary);

uB = zeros(length(boundary), 1);
source_nodes = boundary(y0(boundary) == max(y0(boundary)));
uB(ismember(boundary, source_nodes)) = 1;

uI = LII \ (-LIB * uB);

u = zeros(N,1);
u(boundary) = uB;
u(interior) = uI;
  • Top boundary segment: voltage \(1\)
  • Rest of the boundary: voltage \(0\)
  • MATLAB solves for the unknown interior values
  • The only difference from the unit-resistor case is that L is now weighted.

Visualize the solution

figure;
plot(G, "XData", x0, "YData", y0, ...
        "NodeCData", u, "MarkerSize", 8, "LineWidth", 1.5);
title("Voltage on an irregular network");
colormap turbo;
colorbar;
axis equal off;
  • The node colors show the solved voltage.
  • The shape matters, and the edge resistances matter too.

Traffic

Traffic balance at an intersection

  • Let \(x_k\) be the flow on road \(k\).
  • At each intersection: \[ \text{flow in} = \text{flow out}. \]
  • These are also linear equations.
  • We may also use a few known road counts to determine the unknown flows.

A small road network

  • Roads:
    • \(x_1\): In \(\to\) North
    • \(x_2\): In \(\to\) South
    • \(x_3\): North \(\to\) East
    • \(x_4\): South \(\to\) East
    • \(x_5\): North \(\to\) South
    • \(x_6\): East \(\to\) Out
  • Conservation gives the interior balance equations.
  • Then a couple of measured roads pin down the remaining freedom.

Traffic equations

\[ \begin{aligned} x_1 - x_3 - x_5 &= 0 \\ x_2 + x_5 - x_4 &= 0 \\ x_3 + x_4 - x_6 &= 0 \\ x_6 &= 120 \\ x_5 &= 20 \\ x_1 &= 70 \end{aligned} \]

  • First three rows: conservation at intersections
  • Last three rows: measured or prescribed road values

Matrix form and solve

Atraffic = [
    1 0 -1 0 -1 0;
    0 1  0 -1 1 0;
    0 0  1 1  0 -1;
    0 0  0 0  0  1;
    0 0  0 0  1  0;
    1 0  0 0  0  0
];

btraffic = [0; 0; 0; 120; 20; 70];
xtraffic = Atraffic \ btraffic;
  • The unknown vector is \[ x = \begin{bmatrix} x_1 & x_2 & x_3 & x_4 & x_5 & x_6 \end{bmatrix}^T. \]
  • This is the same Ax = b story in a different application.

Visualize the road flows

Gtraffic = digraph([1 1 2 3 2 4], [2 3 4 4 3 5]);
xy = [0 0; 2 1; 2 -1; 4 0; 6 0];

figure;
p = plot(Gtraffic, "XData", xy(:,1), "YData", xy(:,2), ...
         "LineWidth", 2, "ArrowSize", 14);
labeledge(p, Gtraffic.Edges.EndNodes(:,1), ...
             Gtraffic.Edges.EndNodes(:,2), ...
             compose("%.0f", xtraffic));
title("Solved traffic flows");
axis equal off;
  • Now the unknowns live on the edges instead of the nodes.
  • The edge labels show the solved traffic flow on each road.

Digression: more roads can make traffic worse

  • A famous traffic-network surprise is the Braess paradox.
  • Sometimes adding a new road makes congestion worse, not better.
  • Why?
    • drivers choose selfishly
    • travel time depends on how many drivers use each road
  • That is an interesting network idea, but it is not the same as today’s linear Ax = b traffic model.
  • Let’s watch this nice explanation by Veritasium

Solvers

Same modeling habit, different matrix structure

Problem Matrix feature Good practical choice
Voltage on a graph square, symmetric positive definite \ or Cholesky
Repeated square solve same matrix, new right-hand sides LU
Noisy traffic counts overdetermined least squares QR
Nearly dependent equations rank / conditioning concerns SVD

First MATLAB habit

  • Start with

    x = A \ b;
  • This is much better than using inv(A).

  • MATLAB inspects the matrix and chooses a good strategy internally.

  • But it still helps to know what kind of matrix we have.

What solver makes sense here?

  • For the voltage problem, \(L_{II}\) is symmetric positive definite as long as the resistances are positive.
  • That makes Cholesky especially attractive.
  • If the same square matrix is reused many times, LU is also a natural idea.
  • If traffic data are noisy and we solve a least-squares problem instead, QR is the short answer.
  • SVD is the tool to remember when rank or sensitivity becomes the issue.

Conclusion

Why this matters

  • These are not abstract exercises.
  • Engineers write linear systems from balance laws all the time.
  • The physical meaning changes, but the linear algebra habit stays the same.
  • The next step is a different question:
    • what if we do not want an exact solve?
    • what if we want to minimize prediction error instead?
  • That leads naturally to least squares and gradient descent.

Summary

  • Voltage and traffic both come from local conservation.
  • In the voltage problem, the unknowns are node voltages.
  • In the traffic problem, the unknowns are edge flows.
  • Solver choice depends on the matrix structure.
  • The next lecture shifts from solving equations to minimizing error.